#include <rtdevice.h>

#define DRV_DEBUG
#define LOG_TAG "fram"
#include <drv_log.h>

#define FRAM_I2C_BUS_DEV_NAME   "i2c1"      /*FRAM连接的I2C总线设备名称 */
#define FRAM_ADDR               (0x50)      /* 从机地址 */
#define FRAM_BUFFSIZE           (16)

struct rt_fram_device
{
    struct rt_device parent;
    struct rt_i2c_bus_device *i2c_bus_dev;
    rt_uint16_t device_addr;
};

static struct rt_fram_device fram_dev;

static rt_ssize_t fram_write_bytes(struct rt_fram_device *dev, rt_uint16_t addr, rt_uint8_t *buf, rt_uint16_t len)
{
    struct rt_i2c_msg msgs;
    rt_uint8_t *_buf = (rt_uint8_t *)rt_malloc(len + 1);

    if(_buf == RT_NULL)
    {
        LOG_E("%s:malloc failed", __LINE__);
        return 0;
    }

    if((addr & 0xFF00) == 0)
        msgs.addr = dev->device_addr;
    else
        msgs.addr = dev->device_addr | 0x01;

    _buf[0] = addr & 0xFF;           // 低8位地址
    rt_memcpy(&_buf[1], buf, len);

    msgs.flags = RT_I2C_WR;
    msgs.buf = _buf;
    msgs.len = len + 1;

    /* 调用I2C设备接口传输数据 */
    rt_i2c_transfer(dev->i2c_bus_dev, &msgs, 1);

    return len;
}

static rt_ssize_t fram_read_bytes(struct rt_fram_device *dev, rt_uint16_t addr, rt_uint8_t *buf, rt_uint16_t len)
{
    struct rt_i2c_msg i2c_msg[2];
    rt_uint8_t tempAddr;
    if ((addr & 0xFF00) == 0)
    {
        i2c_msg[0].addr = dev->device_addr;
        i2c_msg[1].addr = dev->device_addr;
    }
    else
    {
        i2c_msg[0].addr = dev->device_addr | 0x01;
        i2c_msg[1].addr = dev->device_addr | 0x01;
    }

    tempAddr = addr & 0xFF;
    /* 发送读地址 */
    i2c_msg[0].flags = RT_I2C_WR;
    i2c_msg[0].buf = &tempAddr;
    i2c_msg[0].len = 1;
    
    /* 读取数据 */
    i2c_msg[1].flags = RT_I2C_RD;
    i2c_msg[1].buf = buf;
    i2c_msg[1].len = len;

    /* 发送读写消息 */
    rt_i2c_transfer(dev->i2c_bus_dev, i2c_msg, 2);

    return len;
}

static rt_ssize_t fram_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    return fram_read_bytes((struct rt_fram_device *)dev, pos, (rt_uint8_t *)buffer, size);
}

static rt_ssize_t fram_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    return fram_write_bytes((struct rt_fram_device *)dev, pos, (rt_uint8_t *)buffer, size);
}

static int rt_hw_fram_init(void)
{
    fram_dev.i2c_bus_dev = (struct rt_i2c_bus_device *)rt_device_find(FRAM_I2C_BUS_DEV_NAME);
    if (fram_dev.i2c_bus_dev == RT_NULL)
    {
        LOG_E("can't find %s device!", FRAM_I2C_BUS_DEV_NAME);
        return RT_ERROR;
    }
    rt_device_open((rt_device_t)fram_dev.i2c_bus_dev, RT_DEVICE_FLAG_RDWR);
    fram_dev.device_addr = FRAM_ADDR;
    fram_dev.parent.type = RT_Device_Class_Char;
    fram_dev.parent.init = RT_NULL;
    fram_dev.parent.open = RT_NULL;
    fram_dev.parent.close = RT_NULL;
    fram_dev.parent.write = fram_write;
    fram_dev.parent.read = fram_read;
    fram_dev.parent.control = RT_NULL;

    rt_device_register(&fram_dev.parent, "fram", RT_DEVICE_FLAG_RDWR);
    return RT_EOK;
}

INIT_DEVICE_EXPORT(rt_hw_fram_init);

